package m

import (
	"GameServer/Common/utils"

	"github.com/globalsign/mgo/bson"
	log "github.com/sirupsen/logrus"

	"GameServer/Game/cache"
	"GameServer/Game/dbmodule"
	"GameServer/Game/errors"
)

type ScryBuffInfo struct {
	Id        int64   `bson:"id"`        // buff的id
	Typ       int64   `bson:"typ"`       // 结算类型 0-计数 1-时间 2-计数和时间
	EndTime   int64   `bson:"endTime"`   // 结束时间
	LeftCount int64   `bson:"leftCount"` // 剩余次数
	Val       float64 `bson:"val"`       // 作用值
}

type ScryerInfoData struct {
	BaseM
	Uid          bson.ObjectId           `bson:"_id" json:"_id"`
	Id           int64                   `bson:"id" json:"id"`                     // 事件id
	GridId       int64                   `bson:"gridId" json:"gridId"`             // 水晶球位置id
	CanReTry     int64                   `bson:"canReTry" json:"canReTry"`         // 重试 0-可以重试 1-不可重试
	State        int64                   `bson:"state" json:"state"`               // 状态 0-没有记录 1-有记录
	ScryBuffList map[int64]*ScryBuffInfo `bson:"scryBuffList" json:"scryBuffList"` // 持有Buff列表
}

func NewScryerInfoData() cache.EntryI {
	return &ScryerInfoData{
		Id:           0,
		GridId:       0,
		CanReTry:     0,
		State:        0,
		ScryBuffList: make(map[int64]*ScryBuffInfo),
	}
}

func (uScryerInfo *ScryerInfoData) Save() (err error) {
	if uScryerInfo.ScryBuffList == nil || len(uScryerInfo.ScryBuffList) == 0 {
		mdata := make(map[string]interface{}, 0)
		mdata["_id"] = uScryerInfo.Uid
		mdata["id"] = uScryerInfo.Id
		mdata["gridId"] = uScryerInfo.GridId
		mdata["canReTry"] = uScryerInfo.CanReTry
		mdata["state"] = uScryerInfo.State
		err = dbmodule.MgoDB.GameDB.Upsert("scryerInfoData", bson.M{"_id": uScryerInfo.Uid}, mdata)
		if err != nil {
			return
		}
		return
	}
	err = dbmodule.MgoDB.GameDB.Upsert("scryerInfoData", bson.M{"_id": uScryerInfo.Uid}, uScryerInfo)
	if err != nil {
		return
	}
	return
}

func (uScryerInfo *ScryerInfoData) Load(key interface{}) (err error) {
	switch key.(type) {
	case string:
		if key.(string) == "" {
			return errors.New("无效的key load, key empty")
		}
		uScryerInfo.Uid = bson.ObjectIdHex(key.(string))
	case bson.ObjectId:
		uScryerInfo.Uid = key.(bson.ObjectId)
	default:
		log.WithFields(log.Fields{
			"method": "ScryerInfoData_Load",
			"data":   key,
		}).Error("无效的key load")
		return errors.New("无效的key load")
	}
	return uScryerInfo.LoadData()
}

//加载数据
func (uScryerInfo *ScryerInfoData) LoadData() (err error) {
	err = dbmodule.MgoDB.GameDB.FindOne("scryerInfoData", bson.M{"_id": uScryerInfo.Uid}, nil, &uScryerInfo)
	if err != nil {
		if err.Error() == "not found" {
			return nil
		}
		return
	}
	if uScryerInfo.ScryBuffList == nil {
		uScryerInfo.ScryBuffList = make(map[int64]*ScryBuffInfo, 0)
	}
	return
}

//更新数据
func (uScryerInfo *ScryerInfoData) Update(val *ScryerInfoData) {
	Cache.Put("scryerInfoData", uScryerInfo.Uid.Hex(), val)
	val.UpdateData()
}

//获取数据，并切返回前刷新数据
func (u *User) GetScryerInfoData() (r *ScryerInfoData) {
	v, _ := Cache.Get("scryerInfoData", u.Uid.Hex())
	r = v.(*ScryerInfoData)
	if r.ScryBuffList == nil {
		r.ScryBuffList = make(map[int64]*ScryBuffInfo, 0)
	}
	bList := r.ScryBuffList
	if len(bList) > 0 {
		deleteList := []int64{}
		for K, V := range bList {
			temp := V
			if temp.Typ == 0 {
				if temp.LeftCount == 0 {
					deleteList = append(deleteList, K)
				}
			} else if temp.Typ == 1 {
				nowT := utils.TNow()
				if nowT.Unix() > temp.EndTime {
					deleteList = append(deleteList, K)
				}
			} else if temp.Typ == 2 {
				nowT := utils.TNow()
				if temp.LeftCount == 0 || nowT.Unix() > temp.EndTime {
					deleteList = append(deleteList, K)
				}
			}
		}
		if len(deleteList) > 0 {
			for _, Value := range deleteList {
				delete(r.ScryBuffList, Value)
			}
		}
	}
	r.Update(r)
	return
}

// --------------Buff-------------------

// 尝试获取指定id的buff,返回前，检查buff的有效性
func (scryData *ScryerInfoData) ScryBuffGet(buffId int64) (result *ScryBuffInfo, findBuff bool) {
	result, findBuff = scryData.ScryBuffList[buffId]
	if !findBuff {
		result = nil
		return
	}
	if result.Typ == 0 && result.LeftCount == 0 {
		delete(scryData.ScryBuffList, buffId)
		scryData.Update(scryData)
		result = nil
		findBuff = false
		return
	}
	if result.Typ == 1 {
		nowT := utils.TNow()
		if nowT.Unix() >= result.EndTime {
			delete(scryData.ScryBuffList, buffId)
			scryData.Update(scryData)
			result = nil
			findBuff = false
			return
		}
	}
	if result.Typ == 2 {
		nowT := utils.TNow()
		if result.LeftCount == 0 || nowT.Unix() >= result.EndTime {
			delete(scryData.ScryBuffList, buffId)
			scryData.Update(scryData)
			result = nil
			findBuff = false
			return
		}
	}
	return
}

// 新增/修改buff
func (scryData *ScryerInfoData) ScryBuffUpsetAndUpdate(val *ScryBuffInfo) {
	scryData.ScryBuffList[val.Id] = val
	scryData.Update(scryData)
	return
}
